package de.jmda.mview.proj;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import org.apache.log4j.Logger;

public class TypesTreeListener
		implements TreeSelectionListener, MouseListener
{
	private final static Logger LOGGER =
			Logger.getLogger(TypesTreeListener.class);

	private DiagramsController diagramsController;
	
	/**
	 * shortcut to {@link DiagramsControllerContext#getTreeTypes()} in
	 * {@link #diagramsController}
	 */
	private JTree tree;
	
	/**
	 * Reference to most lately selected node in {@link #tree}.
	 */
	private DefaultMutableTreeNode selectedNode;
	
	/**
	 * Stores the tree model user object of the {@link #selectedNode}.
	 * <p>
	 * This is necessary because editing the selected node <b>immediately changes
	 * the tree model user object of that node</b>. Storing the user object as
	 * soon as a node gets selected (see {@link #valueChanged(TreeSelectionEvent)})
	 * makes it possible
	 * <ul>
	 *   <li>to update the underlying user object and
	 *   <li>to restore the selected node's user object
	 * <ul>
	 * after editing has finished (see {@link #treeNodesChanged(TreeModelEvent)}).
	 */
	private Object selectedUserObject;
	
	public TypesTreeListener(DiagramsController diagramsController)
	{
		super();
		
		this.diagramsController = diagramsController;

		DiagramsControllerContext controllerContext =
				diagramsController.getDiagramsControllerContext();
		tree = controllerContext.getTreeTypes();
		
		if (tree.getSelectionModel().getSelectionMode() ==
		    TreeSelectionModel.SINGLE_TREE_SELECTION)
		{
			throw new IllegalArgumentException(
					"selection mode of tree has to be " +
					"TreeSelectionModel.SINGLE_TREE_SELECTION");
		}
	}

	/**
	 * Updates {@link #selectedNode} and {@link #selectedUserObject} as soon as
	 * the tree selection changes.
	 *
	 * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
	 */
	@Override
	public void valueChanged(TreeSelectionEvent treeSelectionEvent)
	{
		Object object = tree.getLastSelectedPathComponent();
		
		if (object == null)
		{
			return;
		}
		
		if (false == object instanceof DefaultMutableTreeNode)
		{
			LOGGER.warn(
					"unexpected type of selected node: " + object.getClass().getName());
			return;
		}
		
		selectedNode = (DefaultMutableTreeNode) object;
		selectedUserObject = selectedNode.getUserObject();
	}

	/**
	 * If possible, determines the {@link DefaultMutableTreeNode} on which the
	 * mouse click was received. If successful delegates to {@link
	 * #mouseClicked(MouseEvent, DefaultMutableTreeNode)}.
	 *
	 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
	 */
	@Override
  public void mouseClicked(MouseEvent mouseEvent)
  {
		int selRow = tree.getRowForLocation(mouseEvent.getX(), mouseEvent.getY());

		if(selRow < 0)
		{
			return;
		}
		
		TypesTreeNodeClicked typesTreeNodeClicked =
				new TypesTreeNodeClicked(diagramsController, mouseEvent);
		
		typesTreeNodeClicked.handleEvent();
  }

	@Override
  public void mousePressed(MouseEvent e)
  {
	  // TODO Auto-generated method stub
	  
  }

	@Override
  public void mouseReleased(MouseEvent e)
  {
	  // TODO Auto-generated method stub
	  
  }

	@Override
  public void mouseEntered(MouseEvent e)
  {
	  // TODO Auto-generated method stub
	  
  }

	@Override
  public void mouseExited(MouseEvent e)
  {
	  // TODO Auto-generated method stub
	  
  }
}